using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections.Generic;
using System.Text;

namespace Banshee.Rendering
{
    
    public static class DrawingMethods
    {
        //Draw Glass Hilight
        private static LinearGradientBrush BackBrush;
        private static float _cutMenuItemBack = 1.2f;
        private static void CreateBackBrush(Rectangle rect)
        {
            if (rect.Width > 0 && rect.Height > 0)
            {
                Color[] col = new Color[] { Color.FromArgb(83, 83, 83), Color.FromArgb(83, 83, 83), 
                        Color.FromArgb(83, 83, 0), Color.FromArgb(0, 0, 0), Color.FromArgb(255, 255, 255) };
                float[] pos = new float[] { 0F, 0.47F, 0.53F, 0.75F, 1F };//{ 0.0f, 0.2f, 0.2f, 1.0f };

                ColorBlend blend = new ColorBlend();
                blend.Colors = col;
                blend.Positions = pos;
                BackBrush = new LinearGradientBrush(rect, Color.Transparent, Color.Transparent, LinearGradientMode.Vertical);
                BackBrush.InterpolationColors = blend;

            }

        }
        //185,209,234
        public static void DrawGlassGradient(Graphics g, Rectangle rect, Color LightColor, Color DarkColor, float Angle)
        {
            Rectangle r = rect;
            if (r.Width == 0 || r.Height == 0)
                return;
            Blend glassBlend = new Blend(4);
            glassBlend.Positions[0] = 0f;
            glassBlend.Factors[0] = 0.0f;
            glassBlend.Positions[1] = 0.41f;
            glassBlend.Factors[1] = 0.4f;
            glassBlend.Positions[2] = 0.41f;
            glassBlend.Factors[2] = 0.6f;
            glassBlend.Positions[3] = 1f;
            glassBlend.Factors[3] = 0.2f;

            g.InterpolationMode = InterpolationMode.HighQualityBilinear;
            g.CompositingQuality = CompositingQuality.HighQuality;
            using (LinearGradientBrush lgb = new LinearGradientBrush(r, LightColor, DarkColor, Angle))
            {
                lgb.Blend = glassBlend;
                g.FillRectangle(lgb, r);
            }
        }
        public static void DrawGlassBackGround(Rectangle rect, Graphics g)
        {
            g.InterpolationMode = InterpolationMode.HighQualityBilinear;
            g.CompositingQuality = CompositingQuality.HighQuality;
            if (BackBrush != null)
            {
                BackBrush = null;
            }
            CreateBackBrush(rect);
            g.FillRectangle(BackBrush, rect);


        }
        public static void DrawHighlight(Graphics g, Rectangle rectangle, Color SelectedColor, Color HighLight)
        {
            Color FillColor = HighLight;
            g.InterpolationMode = InterpolationMode.HighQualityBilinear;
            g.CompositingQuality = CompositingQuality.HighQuality;
            using (SolidBrush ForeBrush = new SolidBrush(FillColor))
            {
                g.FillRectangle(ForeBrush, rectangle);
            }
            using (LinearGradientBrush Brush = new LinearGradientBrush(rectangle, SelectedColor, Color.Transparent, LinearGradientMode.Vertical))
            {
                float[] pos = new float[] { 0.0f, 0.40f, 0.5f, 1.0f };
                float[] factors = new float[] { 0f, 0.35f, 1f, 0.3f };
                Blend ColorBlend = new Blend(4);
                ColorBlend.Factors = factors;
                ColorBlend.Positions = pos;
                Brush.Blend = ColorBlend;
                g.FillRectangle(Brush, rectangle);
            }
        }
        public static void DrawSoftHighlight(Graphics g, Rectangle rectangle, Color SelectedColor, Color HighLight)
        {
            using (LinearGradientBrush BackBrush = new LinearGradientBrush(rectangle, SelectedColor, Color.Transparent, LinearGradientMode.Vertical))
            {
                g.FillRectangle(BackBrush, rectangle);
            }
        }
        public static void DrawGradientBorder(Graphics g,
                                Rectangle backRect,
                                GradientItemColors colors)
        {
            // Drawing with anti aliasing to create smoother appearance
            g.SmoothingMode = SmoothingMode.AntiAlias;
            Rectangle backRectI = backRect;
            backRectI.Inflate(1, 1);

            // Finally draw the border around the menu item
            using (LinearGradientBrush borderBrush = new LinearGradientBrush(backRectI, colors.Border1, colors.Border2, 90f))
            {
                // Sigma curve, so go from color1 to color2 and back to color1 again
                borderBrush.SetSigmaBellShape(0.5f);

                // Convert the brush to a pen for DrawPath call
                using (Pen borderPen = new Pen(borderBrush))
                {
                    // Create border path around the entire item
                    using (GraphicsPath borderPath = CreateBorderPath(backRect, _cutMenuItemBack))
                        g.DrawPath(borderPen, borderPath);
                }
            }
        }
        private static GraphicsPath  CreateBorderPath(Rectangle rect,
                                      Rectangle exclude,
                                      float cut)
        {
            // If nothing to exclude, then use quicker method
            if (exclude.IsEmpty)
                return CreateBorderPath(rect, cut);

            // Drawing lines requires we draw inside the area we want
            rect.Width--;
            rect.Height--;

            // Create an array of points to draw lines between
            List<PointF> pts = new List<PointF>();

            float l = rect.X;
            float t = rect.Y;
            float r = rect.Right;
            float b = rect.Bottom;
            float x0 = rect.X + cut;
            float x3 = rect.Right - cut;
            float y0 = rect.Y + cut;
            float y3 = rect.Bottom - cut;
            float cutBack = (cut == 0f ? 1 : cut);

            // Does the exclude intercept the top line
            if ((rect.Y >= exclude.Top) && (rect.Y <= exclude.Bottom))
            {
                float x1 = exclude.X - 1 - cut;
                float x2 = exclude.Right + cut;

                if (x0 <= x1)
                {
                    pts.Add(new PointF(x0, t));
                    pts.Add(new PointF(x1, t));
                    pts.Add(new PointF(x1 + cut, t - cutBack));
                }
                else
                {
                    x1 = exclude.X - 1;
                    pts.Add(new PointF(x1, t));
                    pts.Add(new PointF(x1, t - cutBack));
                }

                if (x3 > x2)
                {
                    pts.Add(new PointF(x2 - cut, t - cutBack));
                    pts.Add(new PointF(x2, t));
                    pts.Add(new PointF(x3, t));
                }
                else
                {
                    x2 = exclude.Right;
                    pts.Add(new PointF(x2, t - cutBack));
                    pts.Add(new PointF(x2, t));
                }
            }
            else
            {
                pts.Add(new PointF(x0, t));
                pts.Add(new PointF(x3, t));
            }

            pts.Add(new PointF(r, y0));
            pts.Add(new PointF(r, y3));
            pts.Add(new PointF(x3, b));
            pts.Add(new PointF(x0, b));
            pts.Add(new PointF(l, y3));
            pts.Add(new PointF(l, y0));

            // Create path using a simple set of lines that cut the corner
            GraphicsPath path = new GraphicsPath();

            // Add a line between each set of points
            for (int i = 1; i < pts.Count; i++)
                path.AddLine(pts[i - 1], pts[i]);

            // Add a line to join the last to the first
            path.AddLine(pts[pts.Count - 1], pts[0]);

            return path;
        }
        private static GraphicsPath CreateBorderPath(Rectangle rect, float cut)
        {
            // Drawing lines requires we draw inside the area we want
            rect.Width--;
            rect.Height--;

            // Create path using a simple set of lines that cut the corner
            GraphicsPath path = new GraphicsPath();
            path.AddLine(rect.Left + cut, rect.Top, rect.Right - cut, rect.Top);
            path.AddLine(rect.Right - cut, rect.Top, rect.Right, rect.Top + cut);
            path.AddLine(rect.Right, rect.Top + cut, rect.Right, rect.Bottom - cut);
            path.AddLine(rect.Right, rect.Bottom - cut, rect.Right - cut, rect.Bottom);
            path.AddLine(rect.Right - cut, rect.Bottom, rect.Left + cut, rect.Bottom);
            path.AddLine(rect.Left + cut, rect.Bottom, rect.Left, rect.Bottom - cut);
            path.AddLine(rect.Left, rect.Bottom - cut, rect.Left, rect.Top + cut);
            path.AddLine(rect.Left, rect.Top + cut, rect.Left + cut, rect.Top);
            return path;
        }
        
    }
    public class GradientItemColors
    {
        public Color InsideTop1;
        public Color InsideTop2;
        public Color InsideBottom1;
        public Color InsideBottom2;
        public Color FillTop1;
        public Color FillTop2;
        public Color FillBottom1;
        public Color FillBottom2;
        public Color Border1;
        public Color Border2;
        public GradientItemColors(Color insideTop1, Color insideTop2,
                                  Color insideBottom1, Color insideBottom2,
                                  Color fillTop1, Color fillTop2,
                                  Color fillBottom1, Color fillBottom2,
                                  Color border1, Color border2)
        {
            InsideTop1 = insideTop1;
            InsideTop2 = insideTop2;
            InsideBottom1 = insideBottom1;
            InsideBottom2 = insideBottom2;
            FillTop1 = fillTop1;
            FillTop2 = fillTop2;
            FillBottom1 = fillBottom1;
            FillBottom2 = fillBottom2;
            Border1 = border1;
            Border2 = border2;
        }
    }
}
